/**
 * @class Ext.chart.axis.Time
 * @extends Ext.chart.axis.Numeric
 *
 * A type of axis whose units are measured in time values. Use this axis
 * for listing dates that you will want to group or dynamically change.
 * If you just want to display dates as categories then use the
 * Category class for axis instead.
 *
 * For example:
 *
 *     axes: [{
 *         type: 'Time',
 *         position: 'bottom',
 *         fields: 'date',
 *         title: 'Day',
 *         dateFormat: 'M d',
 *
 *         constrain: true,
 *         fromDate: new Date('1/1/11'),
 *         toDate: new Date('1/7/11')
 *     }]
 *
 * In this example we're creating a time axis that has as title *Day*.
 * The field the axis is bound to is `date`.
 * The date format to use to display the text for the axis labels is `M d`
 * which is a three letter month abbreviation followed by the day number.
 * The time axis will show values for dates between `fromDate` and `toDate`.
 * Since `constrain` is set to true all other values for other dates not between
 * the fromDate and toDate will not be displayed.
 *
 * @constructor
 */
Ext.define('Ext.chart.axis.Time', { 
 
    extend: 'Ext.chart.axis.Numeric',

    type: 'time',
    
    config: {
        /**
         * @cfg {Boolean} calculateByLabelSize
         * The minimum value drawn by the axis. If not set explicitly, the axis
         * minimum will be calculated automatically.
         */
        calculateByLabelSize: true,

        /**
         * @cfg {String/Boolean} dateFormat
         * Indicates the format the date will be rendered on.
         * For example: 'M d' will render the dates as 'Jan 30', etc.
         */
        dateFormat: false,

        /**
         * @cfg fromDate {Date} The starting date for the time axis.
         */
        fromDate: false,

        /**
         * @cfg toDate {Date} The ending date for the time axis.
         */
        toDate: false,

        /**
         * @cfg step {Array} An array with two components: The first is the unit of the step (Ext.Date.DAY, Ext.Date.MONTH, etc). The second one is the number of units for the step (1, 2, etc.).
         * Default's [Date.DAY, 1]. If this is specified, {@link #steps} config is omitted.
         */
        step: [Ext.Date.DAY, 1],

        /**
         * @cfg {Boolean} constrain
         *
         * If true, the values of the chart will be rendered only if they belong between fromDate and toDate.
         * If false, the time axis will adapt to the new values by adding/removing steps.
         * Default's [Ext.Date.DAY, 1].
         */
        constrain: false
    },

    constructor: function (config) {
        var me = this, label, f, df;
        me.callParent([config]);
        label = me.getLabel() || {};
        df = this.getDateFormat();
        if (df) {
            if (label.renderer) {
                f = label.renderer;
                label.renderer = function(v) {
                    var dv = new Date(f(v));
                    if (isNaN(dv.valueOf())) return f(v);
                    return Ext.Date.format(dv, df);
                };
            } else {
                label.renderer = function(v) {
                    var dv = new Date(v);
                    if (isNaN(dv.valueOf())) return v;
                    return Ext.Date.format(dv, df);
                };
            }
        }
        me.setLabel(label);
    },

    doConstrain: function () {
        var me = this,
            store = me.getChart().getStore(),
            data = [],
            fields = me.getFields(),
            ln = fields.length,
            range = me.getRange(),
            min = range.min, max = range.max, i,
            value, data = [];

        store.each(function(record) {
            for (i = 0; i < ln; i++) {
                value = record.get(fields[i]);
                if (+value < +min) return;
                if (+value > +max) return;
            }
            data.push(record);
        })
        me.getChart().substore = Ext.create('Ext.data.JsonStore', { model: store.model, data: data });
    },

    // Before rendering, set current default step count to be number of records.
    processView: function () {
        var me = this;
        if (me.fromDate) {
            me.setMinimum(+me.fromDate);
        }
        if (me.toDate) {
            me.setMaximum(+me.toDate);
        }
        if (me.constrain) {
            me.doConstrain();
        }
    },

    calcEnds: function() {
        var me = this, range, step = me.getStep();
        if (step) {
            range = me.getRange();
            range = Ext.draw.Draw.snapEndsByDateAndStep(new Date(range.min), new Date(range.max), Ext.isNumber(step) ? [Ext.Date.MILLI, step]: step);
            if (!isNaN(me.getMinimum())) {
                range.from = me.getMinimum();
            }
            if (!isNaN(me.getMaximum())) {
                range.to = me.getMaximum();
            }
            range.step = (range.to - range.from) / range.steps;
            return range;
        } else {
            return me.callParent(arguments);
        }
    }
});
